use axum::{extract::State, Json};
use axum_app_common::{
    crypto,
    error::BizError,
    model::{AppState, BizResponse},
    utils::{Token, TokenPayload},
};
use axum_app_service::service::user_svc;
use serde_json::{json, Value};
use tracing::error;
use uuid::Uuid;

pub async fn login(
    State(state): State<AppState>,
    Json(payload): Json<serde_json::Value>,
) -> Json<Value> {
    let db_conn = state.db_conn;
    let username = payload
        .get("username")
        .map(|s| s.as_str())
        .flatten()
        .unwrap_or("");

    let password = payload
        .get("password")
        .map(|s| s.as_str())
        .flatten()
        .unwrap_or("");

    let user_svc = user_svc::UserSvc::new(&db_conn, None);

    let user = user_svc.find_and_verfy_password(username, password).await;

    let sessionid = Uuid::new_v4().to_string().replace("-", "0");

    let user = match user {
        Ok(Some(user)) => {
            let token = Token::generate_env(&TokenPayload {
                userid: user.userid.clone(),
                sessionid,
            })
            .unwrap();

            BizResponse::success(json!({
                "userid": user.userid,
                "username": user.username,
                "display_name": user.display_name,
                "token": token
            }))
        }
        Ok(None) => {
            BizResponse::fail_with_biz_error(BizError::Unknown, Some("登录失败!用户名或密码错误"))
        }
        Err(err) => BizResponse::fail_with_biz_error(
            BizError::AuthcErr(err.to_string()),
            Some("登录失败!用户名或密码错误"),
        ),
    };

    match serde_json::to_value(user) {
        Ok(v) => Json(v),
        Err(msg) => {
            error!("响应数据转json异常{:?}", msg);
            Json(json!({
                "code": "500",
                "msg": "响应数据转json异常",
            }))
        }
    }
}
